{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "name": "classification.ipynb",
      "provenance": [],
      "private_outputs": true,
      "collapsed_sections": [],
      "toc_visible": true
    },
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.7.4"
    }
  },
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "MhoQ0WE77laV"
      },
      "source": [
        "##### Copyright 2018 The TensorFlow Authors."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "cellView": "form",
        "colab_type": "code",
        "id": "_ckMIh7O7s6D",
        "colab": {}
      },
      "source": [
        "#@title Licensed under the Apache License, Version 2.0 (the \"License\");\n",
        "# you may not use this file except in compliance with the License.\n",
        "# You may obtain a copy of the License at\n",
        "#\n",
        "# https://www.apache.org/licenses/LICENSE-2.0\n",
        "#\n",
        "# Unless required by applicable law or agreed to in writing, software\n",
        "# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
        "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
        "# See the License for the specific language governing permissions and\n",
        "# limitations under the License."
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "cellView": "form",
        "colab_type": "code",
        "id": "vasWnqRgy1H4",
        "colab": {}
      },
      "source": [
        "#@title MIT License\n",
        "#\n",
        "# Copyright (c) 2017 François Chollet\n",
        "#\n",
        "# Permission is hereby granted, free of charge, to any person obtaining a\n",
        "# copy of this software and associated documentation files (the \"Software\"),\n",
        "# to deal in the Software without restriction, including without limitation\n",
        "# the rights to use, copy, modify, merge, publish, distribute, sublicense,\n",
        "# and/or sell copies of the Software, and to permit persons to whom the\n",
        "# Software is furnished to do so, subject to the following conditions:\n",
        "#\n",
        "# The above copyright notice and this permission notice shall be included in\n",
        "# all copies or substantial portions of the Software.\n",
        "#\n",
        "# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n",
        "# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n",
        "# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n",
        "# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n",
        "# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n",
        "# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n",
        "# DEALINGS IN THE SOFTWARE."
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "jYysdyb-CaWM"
      },
      "source": [
        "# Phân loại cơ bản: Dự đoán ảnh quần áo giày dép"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "S5Uhzt6vVIB2"
      },
      "source": [
        "<table class=\"tfo-notebook-buttons\" align=\"left\">\n",
        "  <td>\n",
        "    <a target=\"_blank\" href=\"https://www.tensorflow.org/tutorials/keras/classification\"><img src=\"https://www.tensorflow.org/images/tf_logo_32px.png\" />Xem trên TensorFlow.org</a>\n",
        "  </td>\n",
        "  <td>\n",
        "    <a target=\"_blank\" href=\"https://colab.research.google.com/github/tensorflow/docs/blob/master/site/vi/tutorials/keras/classification.ipynb\"><img src=\"https://www.tensorflow.org/images/colab_logo_32px.png\" />Chạy trên Google Colab</a>\n",
        "  </td>\n",
        "  <td>\n",
        "    <a target=\"_blank\" href=\"https://github.com/tensorflow/docs/blob/master/site/vi/tutorials/keras/classification.ipynb\"><img src=\"https://www.tensorflow.org/images/GitHub-Mark-32px.png\" />Xem mã nguồn trên GitHub</a>\n",
        "  </td>\n",
        "  <td>\n",
        "    <a href=\"https://storage.googleapis.com/tensorflow_docs/docs/site/vi/tutorials/keras/classification.ipynb\"><img src=\"https://www.tensorflow.org/images/download_logo_32px.png\" />Tải notebook</a>\n",
        "  </td>\n",
        "</table>"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "38FdzGHfR4WQ",
        "colab_type": "text"
      },
      "source": [
        "Note: Cộng đồng TensorFlow Việt Nam đã dịch các tài liệu này từ nguyên bản tiếng Anh.\n",
        "Vì bản dịch này dựa trên sự cố gắng từ các tình nguyện viên, nên không thể đám bảo luôn bám sát\n",
        "[Tài liệu chính thức bằng tiếng Anh](https://www.tensorflow.org/?hl=en).\n",
        "Nếu bạn có đề xuất để cải thiện bản dịch này, vui lòng tạo PR đến repository trên GitHub của [tensorflow/docs](https://github.com/tensorflow/docs)\n",
        "\n",
        "Để đăng ký dịch hoặc duyệt lại nội dung bản dịch, các bạn hãy liên hệ \n",
        "[docs@tensorflow.org](https://groups.google.com/a/tensorflow.org/forum/#!forum/docs)."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "FbVhjPpzn6BM"
      },
      "source": [
        "Trong hướng dẫn này, chúng ta sẽ huấn luyện một mô hình mạng neuron để phân loại các hình ảnh về quần áo và giày dép.\n",
        "\n",
        "Đừng ngại nếu bạn không hiểu hết mọi chi tiết, vì chương trình trong hướng dẫn này là một chương trình TensorFlow hoàn chỉnh, và các chi tiết sẽ dần được giải thích ở những phần sau.\n",
        "\n",
        "Hướng dẫn này dùng [tf.keras](https://www.tensorflow.org/guide/keras), một API cấp cao để xây dựng và huấn luyện các mô hình trong TensorFlow."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "jL3OqFKZ9dFg",
        "colab": {}
      },
      "source": [
        "try:\n",
        "  # %tensorflow_version only exists in Colab.\n",
        "  %tensorflow_version 2.x\n",
        "except Exception:\n",
        "  pass"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "dzLKpmZICaWN",
        "colab": {}
      },
      "source": [
        "from __future__ import absolute_import, division, print_function, unicode_literals\n",
        "\n",
        "# TensorFlow and tf.keras\n",
        "import tensorflow as tf\n",
        "from tensorflow import keras\n",
        "\n",
        "# Helper libraries\n",
        "import numpy as np\n",
        "import matplotlib.pyplot as plt\n",
        "\n",
        "print(tf.__version__)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "yR0EdgrLCaWR"
      },
      "source": [
        "## Import tập dữ liệu về quần áo và giày dép từ Fashion MNIST"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "DLdCchMdCaWQ"
      },
      "source": [
        "Chúng ta sẽ dùng tập dữ liệu về quần áo và giày dép từ [Fashion MNIST](https://github.com/zalandoresearch/fashion-mnist), chứa khoảng 70,000 ảnh đen trắng phân thành 10 loại. Mỗi một ảnh là một loại quần áo hoặc giày dép với độ phân giải thấp (28 by 28 pixel), như hình minh hoạ bên dưới:\n",
        "\n",
        "<table>\n",
        "  <tr><td>\n",
        "    <img src=\"https://tensorflow.org/images/fashion-mnist-sprite.png\"\n",
        "         alt=\"Fashion MNIST sprite\"  width=\"600\">\n",
        "  </td></tr>\n",
        "  <tr><td align=\"center\">\n",
        "    <b>Figure 1.</b> <a href=\"https://github.com/zalandoresearch/fashion-mnist\">Fashion-MNIST samples</a> (by Zalando, MIT License).<br/>&nbsp;\n",
        "  </td></tr>\n",
        "</table>\n",
        "\n",
        "Fashion MNIST là tập dữ liệu được dùng để thay thế cho tập dữ liệu [MNIST](http://yann.lecun.com/exdb/mnist/) kinh điển thường dùng cho các chương trình \"Hello, World\" của machine learning trong lĩnh vực thị giác máy tính. Tập dữ liệu kinh điển vừa đề cập gồm  ảnh của các con số (ví dụ 0, 1, 2) được viết tay. Các ảnh này có cùng định dạng tệp và độ phân giải với các ảnh về quần áo và giầy dép chúng ta sắp dùng.\n",
        "\n",
        "Hướng dẫn này sử dụng tập dữ liệu Fashion MNIST, vì đây là một bài toán tương đối phức tạp hơn so với bài toán nhận diện chữ số viết tay. Cả 2 tập dữ liệu (Fashion MNIST và MNIST kinh điển) đều tương đối nhỏ và thường dùng để đảm bảo một giải thuật chạy đúng, phù hợp cho việc kiểm thử và debug.\n",
        "\n",
        "Với tập dữ liệu này, 60.000 ảnh sẽ được dùng để huấn luyện và 10.000 ảnh sẽ đường dùng để đánh giá khả năng phân loại nhận diện ảnh của mạng neuron. Chúng ta có dùng tập dữ liệu Fashion MNIST trực tiếp từ TensorFlow như sau:"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "7MqDQO0KCaWS",
        "colab": {}
      },
      "source": [
        "fashion_mnist = keras.datasets.fashion_mnist\n",
        "\n",
        "(train_images, train_labels), (test_images, test_labels) = fashion_mnist.load_data()"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "t9FDsUlxCaWW"
      },
      "source": [
        "Tập dữ liệu sau khi được tải sẽ trả về 4 mảng NumPy:\n",
        "\n",
        "* 2 mảng `train_images` và `train_labels` là *tập huấn luyện*. Mô hình sẽ học từ dữ liệu của 2 mảng này.\n",
        "* 2 mảng `test_images` vả `test_labels` là *tập kiểm thử*. Sau khi mô hình được huấn luyện xong, chúng ta sẽ chạy thử mô hình với dữ liệu đầu vào từ `test_images` để lấy kết quả, và so sánh kết quả đó với dữ liệu đối ứng từ `test_labels` để đánh giá chất lượng của mạng neuron.\n",
        "\n",
        "Mỗi ảnh là một mảng NumPy 2 chiều, 28x28, với mỗi pixel có giá trị từ 0 đến 255. *Nhãn* là một mảng của các số nguyên từ 0 đến 9, tương ứng với mỗi *lớp* quần áo giày dép:\n",
        "\n",
        "<table>\n",
        "  <tr>\n",
        "    <th>Nhãn</th>\n",
        "    <th>Lớp</th>\n",
        "  </tr>\n",
        "  <tr>\n",
        "    <td>0</td>\n",
        "    <td>Áo thun</td>\n",
        "  </tr>\n",
        "  <tr>\n",
        "    <td>1</td>\n",
        "    <td>Quần dài</td>\n",
        "  </tr>\n",
        "    <tr>\n",
        "    <td>2</td>\n",
        "    <td>Áo liền quần</td>\n",
        "  </tr>\n",
        "    <tr>\n",
        "    <td>3</td>\n",
        "    <td>Đầm</td>\n",
        "  </tr>\n",
        "    <tr>\n",
        "    <td>4</td>\n",
        "    <td>Áo khoác</td>\n",
        "  </tr>\n",
        "    <tr>\n",
        "    <td>5</td>\n",
        "    <td>Sandal</td>\n",
        "  </tr>\n",
        "    <tr>\n",
        "    <td>6</td>\n",
        "    <td>Áo sơ mi</td>\n",
        "  </tr>\n",
        "    <tr>\n",
        "    <td>7</td>\n",
        "    <td>Giày</td>\n",
        "  </tr>\n",
        "    <tr>\n",
        "    <td>8</td>\n",
        "    <td>Túi xách</td>\n",
        "  </tr>\n",
        "    <tr>\n",
        "    <td>9</td>\n",
        "    <td>Ủng</td>\n",
        "  </tr>\n",
        "</table>\n",
        "\n",
        "Mỗi ảnh sẽ được gán với một nhãn duy nhất. Vì tên của mỗi lớp không có trong tập dữ liệu, nên chúng ta có thể định nghĩa ở đây để dùng về sau:"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "IjnLH5S2CaWx",
        "colab": {}
      },
      "source": [
        "class_names = ['Áo thun', 'Quần dài', 'Áo liền quần', 'Đầm', 'Áo khoác',\n",
        "               'Sandal', 'Áo sơ mi', 'Giày', 'Túi xách', 'Ủng']"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "Brm0b_KACaWX"
      },
      "source": [
        "## Khám phá dữ liệu\n",
        "\n",
        "Chúng ta có thể khám phá dữ liệu một chút trước khi huấn luyện mô hình. Câu lệnh sau sẽ cho ta thấy có 60.000 ảnh trong tập huấn luyện, với mỗi ảnh được biểu diễn theo dạng 28x28 pixel:"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "zW5k_xz1CaWX",
        "colab": {}
      },
      "source": [
        "train_images.shape"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "cIAcvQqMCaWf"
      },
      "source": [
        "Tương tự, tập huấn luyện cũng có 60.000 nhãn đối ứng:"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "TRFYHB2mCaWb",
        "colab": {}
      },
      "source": [
        "len(train_labels)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "YSlYxFuRCaWk"
      },
      "source": [
        "Mỗi nhãn là một số nguyên từ 0 đến 9:"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "XKnCTHz4CaWg",
        "colab": {}
      },
      "source": [
        "train_labels"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "TMPI88iZpO2T"
      },
      "source": [
        "Có 10.000 ảnh trong tập kiểm thử, mỗi ảnh cũng được biểu diễn ở dãng 28 x 28 pixel:"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "2KFnYlcwCaWl",
        "colab": {}
      },
      "source": [
        "test_images.shape"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "rd0A0Iu0CaWq"
      },
      "source": [
        "Và tập kiểm thử cũng chứa 10,000 nhãn:"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "iJmPr5-ACaWn",
        "colab": {}
      },
      "source": [
        "len(test_labels)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "ES6uQoLKCaWr"
      },
      "source": [
        "## Tiền xử lý dữ liệu\n",
        "\n",
        "Dữ liệu cần được tiền xử lý trước khi được dùng để huấn luyện mạng neuron. Phân tích ảnh đầu tiên trong tập dữ liệu, chúng ta sẽ thấy các pixel có giá trị từ 0 đến 255:"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "m4VEw8Ud9Quh",
        "colab": {}
      },
      "source": [
        "plt.figure()\n",
        "plt.imshow(train_images[0])\n",
        "plt.colorbar()\n",
        "plt.grid(False)\n",
        "plt.show()"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "Wz7l27Lz9S1P"
      },
      "source": [
        "Chúng ta cần tiền xử lý để mỗi một điểm ảnh có giá trị từ 0 đến 1 (có thể hiểu là 0% đến 100%). Để làm điều này, chúng ta chỉ cần lấy giá trị của pixel chia cho 255. Cần lưu ý rằng việc tiền xử lý này phải được áp dụng đồng thời cho cả *tập huấn luyện* và *tập kiểm thử*:"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "bW5WzIPlCaWv",
        "colab": {}
      },
      "source": [
        "train_images = train_images / 255.0\n",
        "\n",
        "test_images = test_images / 255.0"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "Ee638AlnCaWz"
      },
      "source": [
        "Để chắc chắn việc tiền xử lý diễn ra chính xác, chúng ta có thể in ra 25 ảnh đầu trong *tập huấn luyện* cùng với tên lớp dưới mỗi ảnh."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "oZTImqg_CaW1",
        "colab": {}
      },
      "source": [
        "plt.figure(figsize=(10,10))\n",
        "for i in range(25):\n",
        "    plt.subplot(5,5,i+1)\n",
        "    plt.xticks([])\n",
        "    plt.yticks([])\n",
        "    plt.grid(False)\n",
        "    plt.imshow(train_images[i], cmap=plt.cm.binary)\n",
        "    plt.xlabel(class_names[train_labels[i]])\n",
        "plt.show()"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "59veuiEZCaW4"
      },
      "source": [
        "## Xây dựng mô hình\n",
        "\n",
        "Để xây dựng mạng neuron, chúng tay cần cấu hình các layer của mô hình, và sau đó biên dịch mô hình."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "Gxg1XGm0eOBy"
      },
      "source": [
        "### Thiết lập các layers\n",
        "\n",
        "Thành phần cơ bản của một mạng neuron là các *layer*. Các layer trích xuất các điểm đặc biệt từ dữ liệu mà chúng đón nhận. Khi thực hiện tốt, những điểm đặc biệt này mang nhiều ý nghĩa và phục vụ cho toán của chúng ta.\n",
        "\n",
        "Đa số các mô hình deep learning đều chứa các layer đơn gian được xâu chuỗi lại với nhau. Đa số các layer, ví dụ `tf.keras.layers.Dense`, đều có các trọng số sẽ được học trong quá trình huấn luyện."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "9ODch-OFCaW4",
        "colab": {}
      },
      "source": [
        "model = keras.Sequential([\n",
        "    keras.layers.Flatten(input_shape=(28, 28)),\n",
        "    keras.layers.Dense(128, activation='relu'),\n",
        "    keras.layers.Dense(10, activation='softmax')\n",
        "])"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "gut8A_7rCaW6"
      },
      "source": [
        "Trong mạng neuron trên, lớp đầu tiên, `tf.keras.layers.Flatten`, chuyển đổi định dạng của hình ảnh từ mảng hai chiều (28x28) thành mảng một chiều (28x28 = 784). Tưởng tương công việc của layer này là cắt từng dòng của anh, và ghép nối lại thành một dòng duy nhất nhưng dài gấp 28 lần. Lớp này không có trọng số để học, nó chỉ định dạng lại dữ liệu.\n",
        "\n",
        "Sau layer làm phẳng ảnh (từ 2 chiều thành 1 chiều), phần mạng neuron còn lại gồm một chuỗi hai layer `tf.keras.layers.Dense`. Đây là các layer neuron được kết nối hoàn toàn (mỗi một neuron của layer này kết nối đến tất cả các neuron của lớp trước và sau nó). Layer `Dense` đầu tiên có 128 nút (hoặc neuron). Layer thứ hai (và cuối cùng) là lớp *softmax* có 10 nút, với mỗi nút tương đương với điểm xác suất, và tổng các giá trị của 10 nút này là 1 (tương đương 100%). Mỗi nút chứa một giá trị cho biết xác suất hình ảnh hiện tại thuộc về một trong 10 lớp.\n",
        "\n",
        "### Biên dịch mô hình\n",
        "\n",
        "Trước khi mô hình có thể được huấn luyện, chúng ta cần thêm vài chỉnh sửa. Các chỉnh sửa này được thêm vào trong bước *biên dịch* của mô hình:\n",
        "\n",
        "* *Hàm thiệt hại* — dùng để đo lường mức độ chính xác của mô hình trong quá trình huấn luyện. Chúng ta cần giảm thiểu giá trị của hạm này \"điều khiển\" mô hình đi đúng hướng (thiệt hại càng ít, chính xác càng cao).\n",
        "* *Trình tối ưu hoá* — Đây là cách mô hình được cập nhật dựa trên dữ liệu huấn luyện được cung cấp và hàm thiệt hại.\n",
        "* *Số liệu* — dùng để theo dõi các bước huấn luyện và kiểm thử. Ví dụ sau dùng *accuracy*, tỉ lệ ảnh được phân loại chính xác."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "Lhan11blCaW7",
        "colab": {}
      },
      "source": [
        "model.compile(optimizer='adam',\n",
        "              loss='sparse_categorical_crossentropy',\n",
        "              metrics=['accuracy'])"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "qKF6uW-BCaW-"
      },
      "source": [
        "## Huấn luyện mô hình\n",
        "\n",
        "Huấn luyện mô hình mạng neuron cần các bước sau:\n",
        "\n",
        "1. Cung cấp dữ liệu huấn luyện cho mô hình. Trong ví dụ này, dữ liệu huấn luyện năm trong 2 mảng `train_images` và `train_labels`\n",
        "2. Mô hình sẽ học cách liên kết ảnh với nhãn.\n",
        "3. Chúng ta sẽ yêu cầu mô hình đưa ra dự đoán từ dữ liệu của tập kiểm thử, trong ví dụ này là mảng `test_images`, sau đó lấy kết quả dự đoán đối chiếu với nhãn trong mảng `test_labels`.\n",
        "\n",
        "Để bắt đầu huấn luyện, gọi hàm `model.fit`. Hàm này được đặt tên `fit` vì nó sẽ \"fit\" (\"khớp\") mô hình với dữ liệu huấn luyện:"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "xvwvpA64CaW_",
        "colab": {}
      },
      "source": [
        "model.fit(train_images, train_labels, epochs=10)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "W3ZVOhugCaXA"
      },
      "source": [
        "Trong quá trình huấn luyện, các số liệu như thiệt hại và hay độ chính xác được hiển thị. Với dữ liệu huấn luyện này, mô hình đạt đến độ accuracy vào khoảng 0.88 (88%)."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "oEw4bZgGCaXB"
      },
      "source": [
        "## Đánh giá mô hình\n",
        "\n",
        "Tiếp theo, chúng đánh giá các chất lượng của mô hình bằng tập kiểm thử:"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "VflXLEeECaXC",
        "colab": {}
      },
      "source": [
        "test_loss, test_acc = model.evaluate(test_images,  test_labels, verbose=2)\n",
        "\n",
        "print('\\nTest accuracy:', test_acc)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "yWfgsmVXCaXG"
      },
      "source": [
        "Đến thời điểm này, chúng ta thấy rằng độ accuracy của mô hình, khi đánh giá bằng tập kiểm thử, hơi thấp hơn so với số liệu trong quá trình huấn luyện. Khoảng cách giữa hai độ accuracy khi huấn luyện và khi kiểm thử thể hiện sự *overfitting*. Overfitting xảy ra khi một mô hình ML hoạt động kém hơn khi được cung cấp các đầu vào mới, mà mô hình chưa từng thấy trước đây trong quá trình đào tạo."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "xsoS7CPDCaXH"
      },
      "source": [
        "## Đưa ra dự đoán\n",
        "\n",
        "Với một mô hình đã được đào tạo, chúng ta có thể dùng nó để đưa ra dự đoán với một số ảnh."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "Gl91RPhdCaXI",
        "colab": {}
      },
      "source": [
        "predictions = model.predict(test_images)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "x9Kk1voUCaXJ"
      },
      "source": [
        "Ở đây, mô hình sẽ dự đoán nhãn cho từng hình ảnh trong bộ thử nghiệm. Hãy xem dự đoán đầu tiên:"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "3DmJEUinCaXK",
        "colab": {}
      },
      "source": [
        "predictions[0]"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "-hw1hgeSCaXN"
      },
      "source": [
        "Trong ví dụ này, dự đoán là một mảng 10 số thực, mỗi số tương ứng với \"độ tự tin\" của mô hình rằng ảnh đó thuộc về nhãn đó. Chúng ta có thể thấy nhãn nào có độ tư tin cao nhất:"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "qsqenuPnCaXO",
        "colab": {}
      },
      "source": [
        "np.argmax(predictions[0])"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "E51yS7iCCaXO"
      },
      "source": [
        "Vậy là mô hình tự tin nhất rằng ảnh này là một loại ủng, hoặc `class_names[9]`. Đối chiếu với nhãn trong tập kiểm thử, ta thấy dự đoán này là đúng:"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "Sd7Pgsu6CaXP",
        "colab": {}
      },
      "source": [
        "test_labels[0]"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "ygh2yYC972ne"
      },
      "source": [
        "Ta thử vẽ biểu đồ để xem các dự đoán trên cả 10 lớp của mô hình."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "DvYmmrpIy6Y1",
        "colab": {}
      },
      "source": [
        "def plot_image(i, predictions_array, true_label, img):\n",
        "  predictions_array, true_label, img = predictions_array, true_label[i], img[i]\n",
        "  plt.grid(False)\n",
        "  plt.xticks([])\n",
        "  plt.yticks([])\n",
        "\n",
        "  plt.imshow(img, cmap=plt.cm.binary)\n",
        "\n",
        "  predicted_label = np.argmax(predictions_array)\n",
        "  if predicted_label == true_label:\n",
        "    color = 'blue'\n",
        "  else:\n",
        "    color = 'red'\n",
        "\n",
        "  plt.xlabel(\"{} {:2.0f}% ({})\".format(class_names[predicted_label],\n",
        "                                100*np.max(predictions_array),\n",
        "                                class_names[true_label]),\n",
        "                                color=color)\n",
        "\n",
        "def plot_value_array(i, predictions_array, true_label):\n",
        "  predictions_array, true_label = predictions_array, true_label[i]\n",
        "  plt.grid(False)\n",
        "  plt.xticks(range(10))\n",
        "  plt.yticks([])\n",
        "  thisplot = plt.bar(range(10), predictions_array, color=\"#777777\")\n",
        "  plt.ylim([0, 1])\n",
        "  predicted_label = np.argmax(predictions_array)\n",
        "\n",
        "  thisplot[predicted_label].set_color('red')\n",
        "  thisplot[true_label].set_color('blue')"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "d4Ov9OFDMmOD"
      },
      "source": [
        "Chúng ta có thể nhìn vào ảnh 0th, các dự đoán, và mảng dự đoán.\n",
        "Nhãn dự đoán đúng màu xanh và nhãn sai màu đỏ. Con số là số phần trăm của các nhãn được dự đoán."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "HV5jw-5HwSmO",
        "colab": {}
      },
      "source": [
        "i = 0\n",
        "plt.figure(figsize=(6,3))\n",
        "plt.subplot(1,2,1)\n",
        "plot_image(i, predictions[i], test_labels, test_images)\n",
        "plt.subplot(1,2,2)\n",
        "plot_value_array(i, predictions[i],  test_labels)\n",
        "plt.show()"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "Ko-uzOufSCSe",
        "colab": {}
      },
      "source": [
        "i = 12\n",
        "plt.figure(figsize=(6,3))\n",
        "plt.subplot(1,2,1)\n",
        "plot_image(i, predictions[i], test_labels, test_images)\n",
        "plt.subplot(1,2,2)\n",
        "plot_value_array(i, predictions[i],  test_labels)\n",
        "plt.show()"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "kgdvGD52CaXR"
      },
      "source": [
        "Thử vẽ biểu đồ với vài ảnh và dự đoán đi kèm. Chú ý thấy rằng mô hình đôi khi dự đoán sai dù điểm tự tin rất cao."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "hQlnbqaw2Qu_",
        "colab": {}
      },
      "source": [
        "# Plot the first X test images, their predicted labels, and the true labels.\n",
        "# Color correct predictions in blue and incorrect predictions in red.\n",
        "num_rows = 5\n",
        "num_cols = 3\n",
        "num_images = num_rows*num_cols\n",
        "plt.figure(figsize=(2*2*num_cols, 2*num_rows))\n",
        "for i in range(num_images):\n",
        "  plt.subplot(num_rows, 2*num_cols, 2*i+1)\n",
        "  plot_image(i, predictions[i], test_labels, test_images)\n",
        "  plt.subplot(num_rows, 2*num_cols, 2*i+2)\n",
        "  plot_value_array(i, predictions[i], test_labels)\n",
        "plt.tight_layout()\n",
        "plt.show()"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "R32zteKHCaXT"
      },
      "source": [
        "Cuối cùng, dùng mô hình để đưa ra dự đoán về một ảnh duy nhất."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "yRJ7JU7JCaXT",
        "colab": {}
      },
      "source": [
        "# Grab an image from the test dataset.\n",
        "img = test_images[1]\n",
        "\n",
        "print(img.shape)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "vz3bVp21CaXV"
      },
      "source": [
        "Các mô hình `tf.keras` được tối ưu hóa để đưa ra dự đoán về một *lô* hoặc bộ sưu tập các ví dụ cùng một lúc. Theo đó, mặc dù bạn đang sử dụng một ảnh duy nhất, bạn cần thêm nó vào list:"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "lDFh5yF_CaXW",
        "colab": {}
      },
      "source": [
        "# Add the image to a batch where it's the only member.\n",
        "img = (np.expand_dims(img,0))\n",
        "\n",
        "print(img.shape)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "EQ5wLTkcCaXY"
      },
      "source": [
        "Dự đoán nhãn cho ảnh này:"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "o_rzNSdrCaXY",
        "colab": {}
      },
      "source": [
        "predictions_single = model.predict(img)\n",
        "\n",
        "print(predictions_single)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "6Ai-cpLjO-3A",
        "colab": {}
      },
      "source": [
        "plot_value_array(1, predictions_single[0], test_labels)\n",
        "_ = plt.xticks(range(10), class_names, rotation=45)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "cU1Y2OAMCaXb"
      },
      "source": [
        "`model.predict` trả về một list của lists — mỗi list cho mỗi ảnh trong lô dữ liệu. Lấy dự đoán cho hình ảnh trong lô:"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "2tRmdq_8CaXb",
        "colab": {}
      },
      "source": [
        "np.argmax(predictions_single[0])"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "YFc2HbEVCaXd"
      },
      "source": [
        "Mô hình dự đoán ảnh này có nhãn là đúng như mong muốn."
      ]
    }
  ]
}